#pragma once

#include <iostream>
#include <map>
#include <vector>
#include <functional>

#include <SDL.h>
#include <SDL_ttf.h>

#include "constheader.h"

SDL_Rect r = {0, 0, 0, 0};
SDL_Color c = {0, 0, 0, 0};

struct NameSize
{
    std::string name;
    unsigned int size;
};

class LessNameSize
{
public:
    bool operator() (const NameSize& left, const NameSize& right)
    {
        if (left.size < right.size)
            return true;
        if (left.size == right.size)
            return std::less<std::string>()(left.name, right.name);
        return false;
    }
};

class TextPainter
{
public:
    class Text
    {
    public:
        Text(std::function<void(std::string*)> updater) 
            : updater_(updater), 
            how_often_(200),
            name_("usual_name"),
            content_("usual_text"),
            pos_(r),
            color_(c),
            size_(10),
            content_sur_(nullptr),
            time_(0) {}
        void Update()
        {
            updater_(&content_);
        }
        bool CanUpdate()
        {
            if (SDL_GetTicks() - time_ > how_often_)
            {
                time_ = SDL_GetTicks();
                return true;
            }
            return false;
        }
        const std::string& GetName() const
        {
            return name_;
        }
        const SDL_Surface* GetContent() const
        {
            return content_sur_;
        }
    private:
        std::function<void(std::string*)> updater_;
        SDL_Rect pos_;
        SDL_Color color_;
        std::string name_;   
        unsigned int how_often_; // ms
        std::string content_;
        int size_;
        SDL_Surface* content_sur_;
        unsigned int time_;
    };
    TTF_Font* GetFont(const std::string& name, unsigned int size)
    {
        NameSize loc = {name, size};
        if (fonts_[loc] == nullptr)
        {
            TTF_Font* font = TTF_OpenFont(name.c_str(), size);
            if (font == nullptr)
                SYSTEM_STREAM << "Cannot load font " << name << " with size " << size << std::endl;
            fonts_[loc] = font;
        }
        return fonts_[loc];
    }
    void Process()
    {
        for (auto it = texts_.begin(); it != texts_.end(); ++it)
        {
            if ((**it).CanUpdate())
                (**it).Update();
            // TODO: Draw
        }
    }
    void AddText(Text* text)
    {
        texts_.push_back(text);
    }
    Text* TakeText(const std::string& name)
    {
        for (int i = 0; i < texts_.size(); ++i)
            if (name == texts_[i]->GetName())
                return texts_[i];
        return nullptr;
    }
private:
    std::vector<Text*> texts_;
    std::map<NameSize, TTF_Font*, LessNameSize> fonts_;
};